package src;

/**
 * The Sine class, in which implement Expression Interface
 * represents the Sine Expression (i.e., sin(a), where a is an expression)
 * A sine expression can be evaluated, derived and return its last operation symbol.
 *
 * @author Intro111 Staff
 */


public class Sine implements Expression {

    private Expression exp;

    /**
     * Constructor that creates a sine expression
     *
     * @param exp the expression
     * @throws RunTimeException for null input expression
     */
    public Sine(Expression exp) {
        if (exp == null) {
            throw new RuntimeException("Sine constructor got a null argument.");
        }

        this.exp = exp;
    }

    /**
     * Returns the last operation symbol of Sine Expression
     *
     * @return String "sin" that represents the last operation
     */
    public String getLastOperationSymbol() {
        return "sin";
    }

    /**
     * Evaluates the sine expression
     *
     * @return double that represents the evaluation of the sine expression
     */
    public double evaluate() {
        return Math.sin(exp.evaluate());
    }

    /**
     * Derives the sine expression by a variable.
     *
     * @param var the variable to derive by
     * @return the derived expression by param var
     * @throws RunTimeException for a null var
     */
    public Expression derivative(Variable var) {
        if (var == null) {
            throw new RuntimeException("Sine derivative(Variable var) got a null argument.");
        }

        return new Multiplication(new Cosine(exp), exp.derivative(var));
    }

    /**
     * Compares this sine expression to the specified object.
     * The result is true if and only if the argument is not null, the argument is instance of sine expression and the sub-expressions are equals.
     *
     * @param other The object to compare this expression against
     * @return true if the given object represents an expression equivalent to this expression, false otherwise
     */
    public boolean equals(Object other) {
        return ((other instanceof Sine) &&
                (exp.equals(((Sine) other).exp)));
    }

    /**
     * Returns a string representing the sine expression.
     *
     * @return String that represents the sine expression
     */
    public String toString() {
        return getLastOperationSymbol() + "(" + exp.toString() + ")";
    }

}
